#define		SAFE_FREE(p)				{ if (p) { free((p)); (p) = NULL; } }
#define		SAFE_DELETE(p)				{ if (p) { delete (p); (p) = NULL; } }
#define		SAFE_DELETE_ARRAY(p)		{ if (p) { delete [](p); (p) = NULL; } }
#define		NUM_ARRAY_ELEMENTS(p)		((int) sizeof(p) / sizeof(p[0]))

#ifndef		LOG_ASSERT
#define		LOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
#endif

namespace android {
namespace hardware {
namespace camera {
namespace device {
namespace V3_4 {
namespace implementation {

template <class T>
class MLObjectarray {
private:
    T *m_elements;
    const int min_size;
    int m_max_size;
    int m_size;
public:
    MLObjectarray(int initial_capacity = 2)
        :m_elements(new T[initial_capacity]),
        m_max_size(initial_capacity),
        m_size(0),
        min_size(initial_capacity){
    }

    ~MLObjectarray(){SAFE_DELETE_ARRAY(m_elements);}

    void size(int new_size){
        if(new_size != capacity()){
            T *new_elements = new T[new_size];
            //LOG_ASSERT(new_elements, "out of memory:size=%d,capacity=%d", new_size, m_max_size);
            const int n = (new_size < capacity()) ? new_size : capacity();
            for (int i = 0; i < n; i++) {
                new_elements[i] = m_elements[i];
            }
            SAFE_DELETE_ARRAY(m_elements);
            m_elements = new_elements;
            m_max_size = new_size;
            m_size = (m_size < new_size) ? m_size : new_size;
        }
    }

    inline int size() const { return m_size; }
    inline bool isEmpty() const { return (m_size < 1); }
    inline int capacity() const { return m_max_size; }
    inline T &operator[](int index) { return m_elements[index]; }
    inline const T &operator[](int index) const { return m_elements[index]; }

    int put(T object) {
        if (object) {
            if (size() >= capacity()) {
                size(capacity() ? capacity() * 2 : 2);
            }
            m_elements[m_size++] = object;
        }
        return m_size;
    }
    /**
	 * remove T which posisioned on index
	 */
    T remove(int index) {
        T obj = m_elements[index];
        for (int i = index; i < m_size - 1; i++) {
            m_elements[i] = m_elements[i+1];
        }
        m_size--;
        return obj;
    }
    /**
     * search the T object and remove if exist
     */
    void removeObject(T object) {
        for (int i = 0; i < size(); i++) {
            if (m_elements[i] == object) {
                remove(i);
                break;
            }
        }
    }
    /**
     * get last T and remove from this array ¥
     * this is faster than remove(size()-1)
     */
    inline T last() {
        if (m_size > 0)
        return m_elements[--m_size];
        else
        return NULL;
    }
    /**
     * search the T object and return it's index
     * if the T is not in this array, return -1
     */
    int getIndex(const T object) {
        int result = -1;
        for (int i = 0; i < size(); i++) {
            if (m_elements[i] == object) {
                result = i;
                break;
            }
        }
        return result;
    }

    /**
     * clear the T array but never delete actual T instance
     */
    inline void clear() {
        size(min_size);
        m_size = 0;
    }
};



}  // namespace implementation
}  // namespace V3_4
}  // namespace device
}  // namespace camera
}  // namespace hardware
}  // namespace android
